package com.hwtx.protocol.dubbo.rpc;

import com.google.common.collect.Maps;

import com.hwtx.protocol.dubbo.code.DubboConstants;
import com.hzgj.bcl.soa.api.IdempotentIdGen;
import com.hzgj.bcl.soa.rpc.RpcContext;
import com.hzgj.bcl.soa.rpc.client.RequestOptions;
import com.hzgj.bcl.soa.rpc.message.Message;
import com.hzgj.bcl.soa.rpc.message.MethodCall;
import com.hzgj.bcl.soa.spi.MessageHandleFactory;
import com.hzgj.bcl.soa.util.Constants;
import com.hzgj.bcl.util.lang.StrKit;

import java.lang.reflect.Method;
import java.util.Map;

import static com.hwtx.protocol.dubbo.code.DubboConstants.GROUP_KEY;
import static com.hwtx.protocol.dubbo.code.DubboConstants.INTERFACE_KEY;
import static com.hwtx.protocol.dubbo.code.DubboConstants.MESSAGE_HEADER_DUBBO_ATTACHMENT;
import static com.hwtx.protocol.dubbo.code.DubboConstants.MESSAGE_HEADER_DUBBO_BIZID;
import static com.hwtx.protocol.dubbo.code.DubboConstants.MESSAGE_HEADER_DUBBO_TRACEID;
import static com.hwtx.protocol.dubbo.code.DubboConstants.MESSAGE_HEADER_DUBBO_WHOIM;
import static com.hwtx.protocol.dubbo.code.DubboConstants.VERSION_KEY;
import static com.hzgj.bcl.soa.util.Constants.MESSAGE_HEADER_METHOD_ARGS;
import static com.hzgj.bcl.soa.util.Constants.MESSAGE_HEADER_METHOD_PARAMETERTYPES;
import static com.hzgj.bcl.soa.util.Constants.MESSAGE_HEADER_SERVICE_VERSION;

/**
 * Created by warning on 2016/11/4.
 */
public class DubboMessageHandleFactory implements MessageHandleFactory {

    @Override
    public Message buildRequestMessage(Method method, Object[] args, RequestOptions options) {

        Map<String, String> attachments = Maps.newHashMap();
        attachments.put(MESSAGE_HEADER_DUBBO_TRACEID, RpcContext.getContextId());
        if (StrKit.isBlank(RpcContext.getWhoIm())) {
            attachments.put(MESSAGE_HEADER_DUBBO_WHOIM, options.getSource());
        } else {
            attachments.put(MESSAGE_HEADER_DUBBO_WHOIM, RpcContext.getWhoIm());
        }
        if (options.getMethodDef() != null) {
            IdempotentIdGen idempotentIdGen = options.getMethodDef().getIdempotentIdGen();
            if (idempotentIdGen != null) {
                String continueId = idempotentIdGen.getContinueId();
                if (StrKit.isBlank(continueId)) {
                    throw new RuntimeException("idempotentIdGen exist,but continueId is null");
                } else {
                    attachments.put(MESSAGE_HEADER_DUBBO_BIZID, continueId);
                }
            }
        }

        attachments.put(GROUP_KEY, options.getReferenceDef().getGroup());
        attachments.put(VERSION_KEY, options.getReferenceDef().getVersion());
        attachments.put(INTERFACE_KEY, options.getReferenceDef().getService());
        Message message = new Message();

        message.putHeader(MESSAGE_HEADER_DUBBO_ATTACHMENT, attachments)
                .putHeader(MESSAGE_HEADER_METHOD_PARAMETERTYPES, method.getParameterTypes())
                .putHeader(MESSAGE_HEADER_METHOD_ARGS, args);
        return message;
    }

    @Override
    public Message buildResponse(Long req_id, Object reply, boolean is_exception) {
        return new Message(reply);
    }

    @Override
    public Message buildErrorResponse(Throwable throwable, Map<String, Object> headers) {
        return new Message().setPayload(throwable).putHeaders(headers).putHeader(Constants.MESSAGE_TYPE, Message.EXC_RSP);
    }

    @Override
    public <T> T handleResponse(Object response) throws Exception {
        return (T) response;
    }

    @Override
    public String getName() {
        return DubboConstants.DUBBO_PROTOCOL;
    }
}
